package com.CampaignManager.server;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.logging.Logger;

import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;
import javax.jdo.Query;

import com.CampaignManager.shared.CampaignService;
import com.CampaignManager.shared.CityDTO;
import com.CampaignManager.shared.JobDTO;
import com.CampaignManager.shared.NotLoggedInException;
import com.CampaignManager.shared.PlayerCityDTO;
import com.CampaignManager.shared.PlayerDTO;
import com.CampaignManager.shared.ResourceAmountDTO;
import com.CampaignManager.shared.UnitDTO;
import com.CampaignManager.shared.UnitTypeDTO;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

@SuppressWarnings({"unchecked","serial"})
public class CampaignServiceImpl extends RemoteServiceServlet implements CampaignService {
	
	public static final Logger LOG = Logger.getLogger(CampaignServiceImpl.class.getName());
	public static final PersistenceManagerFactory PMF = JDOHelper.getPersistenceManagerFactory("transactions-optional");
	
	public PlayerDTO[] login(String requestUri) throws NotLoggedInException  {
	    
		List<PlayerDTO> playerList = new ArrayList<PlayerDTO>();
		
		PersistenceManager pm = getPersistenceManager();
    	try {
    		Query q = pm.newQuery(Player.class);
			q.setOrdering("email");
			List<Player> players = (List<Player>) q.execute();			
			for (Player player : players) {
				PlayerDTO p = new PlayerDTO();
				if (player.getEmail().equals(getUser().getEmail())) {
					SetCurrentUserInfo(p, requestUri);
				}					
				GetPlayerUnits(player, pm);
				copy(player,p);
				playerList.add(p);	
			}
									
		} finally {
    		pm.close();
    	}
		return (PlayerDTO[]) playerList.toArray(new PlayerDTO[0]);
	}
	
	public PlayerDTO CreateNewPlayer(String requestUri, String name, String desc, String faction) throws NotLoggedInException  {
		
		Player thisPlayer = new Player();
		
		PersistenceManager pm = getPersistenceManager();
    	try {
			
			thisPlayer.setCharacterName(name);
			thisPlayer.setCharacterDescription(desc);
			thisPlayer.setEmail(getUser().getEmail());
			thisPlayer.setNickName(getUser().getNickname());
			thisPlayer.setLevel(1L);
			PlayerResource pr = thisPlayer.getResource("Gold");
			pr.setAmount(40L);
			
			//find starting spot
			Query p = pm.newQuery(City.class);
			p.setFilter("faction == f");
			p.declareParameters("String f");			
			List<City> cities = (List<City>) p.execute(faction);
			
			if (cities.size() <= 0) {
				thisPlayer.setOriginLatitude(22.512556954051437);
				thisPlayer.setOriginLongitude(-148.9801025390625);				
			} else {			
				Random r = new Random();
				int index = r.nextInt();
				index = Math.abs(index);
				index = index % cities.size();
				City c = cities.get(index);
				thisPlayer.setOriginLatitude(c.getLatitude()-.02);
				thisPlayer.setOriginLongitude(c.getLongitude()-.02);
			}
			thisPlayer.setMilesToTravel(.0);
			thisPlayer.setMoveStart(new Date());
						
			pm.makePersistent(thisPlayer);
			
    	} finally {
    		pm.close();
    	}
		
		PlayerDTO info = new PlayerDTO();
		SetCurrentUserInfo(info, requestUri);		
		copy(thisPlayer,info);
				
		return info;		
	}
	
	public void SetDoneTutorial(String tut) throws NotLoggedInException  {
		
		PersistenceManager pm = getPersistenceManager();
    	try {
    		Player thisPlayer = null;
    		
    		Query p = pm.newQuery(Player.class);
    		p.setFilter("email == e");
    		p.declareParameters("String e");
    		List<Player> players = (List<Player>) p.execute(getUser().getEmail());
    		if (players.size() > 0) {
    			thisPlayer = players.get(0);
    		}
    		
    		if (thisPlayer != null) {
    			if (tut.equals("Map"))
    				thisPlayer.setDoneMapTutorial(true);
    			if (tut.equals("Job"))
    				thisPlayer.setDoneJobTutorial(true);
    			if (tut.equals("Espionage"))
    				thisPlayer.setDoneEspionageTutorial(true);
    			if (tut.equals("Hire"))
    				thisPlayer.setDoneHireTutorial(true);
    		}
									
		} finally {
    		pm.close();
    	}		
	}
	
	public Long AddCity(CityDTO city) throws NotLoggedInException {
		
		City c = new City();
		
		PersistenceManager pm = getPersistenceManager();
    	try {
			
			c.setName(city.getName());
			c.setFaction(city.getFaction());
			c.setLatitude(city.getLatitude());
			c.setLongitude(city.getLongitude());
			
			pm.makePersistent(c);
			
    	} finally {
    		pm.close();
    	}

    	return c.getId();
	}

	public void UpdateCityLocation(Long id, double lat, double lng) throws NotLoggedInException {
		checkLoggedIn();
		PersistenceManager pm = getPersistenceManager();		
		try {
			Query p = pm.newQuery(City.class);
			p.setFilter("id == i");
			p.declareParameters("Long i");
			List<City> cities = (List<City>) p.execute(id);
			for (City c : cities) {				
				c.setLatitude(lat);
				c.setLongitude(lng);
			}
		} finally {
			pm.close();
		}
	}
	
	public CityDTO[] GetCities() throws NotLoggedInException {
		checkLoggedIn();
		
		PersistenceManager pm = getPersistenceManager();
		
		List<CityDTO> cityList = new ArrayList<CityDTO>();		
		try {
			Query q = pm.newQuery(City.class);
			List<City> cities = (List<City>) q.execute();			
			for (City city : cities) {
				CityDTO c = new CityDTO();
				c.setCityId(city.getId());
				c.setName(city.getName());
				c.setLatitude(city.getLatitude());
				c.setLongitude(city.getLongitude());
				c.setFaction(city.getFaction());
				
				for (CityRelate cr : city.getRelations()) {
					ResourceAmountDTO prc = new ResourceAmountDTO();
					prc.setResource(cr.getOtherCity());
					prc.setAmount(cr.getValue());
					c.getRelations().add(prc);
				}
				
				cityList.add(c);		
			}
		} finally {
			pm.close();
		}
		return (CityDTO[]) cityList.toArray(new CityDTO[0]);
	}
	
	public void UpdateArmyDestination(String email, double originLat, double originLong, double destLat, double destLong, double miles) throws NotLoggedInException {
		checkLoggedIn();
		PersistenceManager pm = getPersistenceManager();		
		try {
			Query p = pm.newQuery(Player.class);
			p.setFilter("email == e");
			p.declareParameters("String e");
			List<Player> players = (List<Player>) p.execute(email);
			for (Player player : players) {
				player.setOriginLatitude(originLat);
				player.setOriginLongitude(originLong);
				player.setDestLatitude(destLat);
				player.setDestLongitude(destLong);
				player.setMilesToTravel(miles);
				player.setMoveStart(new Date());
			}
		} finally {
			pm.close();
		}		
	}
	
	public boolean CheckExistingPendingJob() throws NotLoggedInException {
		checkLoggedIn();
		PersistenceManager pm = getPersistenceManager();		
		try {
			Query p = pm.newQuery(Job.class);
			
			p.setFilter("email == e && status == j");
			p.declareParameters("String e, String j");
			List<Job> jobs = (List<Job>) p.execute(getUser().getEmail(),"Pending");
			if (jobs.isEmpty())
				return false;
			else
				return true;
		} finally {
			pm.close();
		}
	}
	
	public String CreateJob(JobDTO job) throws NotLoggedInException {
		checkLoggedIn();
		
		Job j = new Job();
		
		PersistenceManager pm = getPersistenceManager();
    	try {
    		Player player = getPlayer(getUser().getEmail(),pm);
    	    		
			j.setStatus("Pending");
			j.setJobType(job.getJobType());
			j.setEmail(getUser().getEmail());
			j.setJobFor(job.getJobFor());
			j.setDestination(job.getDestination());
			j.setReward(job.getReward());
			j.setTaken(new Date());
			j.setStoryMessageID(job.getStoryMessageID());
			j.setStorySubject(job.getStorySubject());
			
			player.getJobs().add(j);
			
    	} finally {
    		pm.close();
    	}
    	
    	return KeyFactory.keyToString(j.getId());
	}

	public JobDTO[] GetJobs(String email) throws NotLoggedInException {
		checkLoggedIn();
		
		PersistenceManager pm = getPersistenceManager();
		
		List<JobDTO> jobList = new ArrayList<JobDTO>();		
		try {
			Query q = pm.newQuery(Job.class);
			q.setFilter("email == e");
			q.declareParameters("String e");
			q.setOrdering("status desc, taken");
			List<Job> cities = (List<Job>) q.execute(email);			
			for (Job job : cities) {
				JobDTO j = new JobDTO();
				copy(job,j);
				jobList.add(j);		
			}
		} finally {
			pm.close();
		}
		return (JobDTO[]) jobList.toArray(new JobDTO[0]);
	}
	
	public void CompleteJob(JobDTO job) throws NotLoggedInException {
		checkLoggedIn();
		PersistenceManager pm = getPersistenceManager();		
		try {
			Player player = getPlayer(getUser().getEmail(),pm);
			
			Query q = pm.newQuery(Job.class);
			q.setFilter("id == i");
			q.declareParameters("Long i");
			List<Job> jobs = (List<Job>) q.execute(KeyFactory.stringToKey(job.getId()));
			Job j = jobs.get(0);
			
			PlayerCity playerCityRelate = player.getCity(job.getJobFor());
			
			if (job.getJobType().equals("Warmonger")) {
				
				Query cityQuery = pm.newQuery(City.class);
				cityQuery.setFilter("name == i");
				cityQuery.declareParameters("String i");
				List<City> cities = (List<City>) cityQuery.execute(job.getJobFor());
				City city = cities.get(0);
				CityRelate cr = city.getRelation(job.getDestination());
				cr.setValue(cr.getValue()-job.getReward());
				
			} else if (job.getJobType().equals("Surveillance") || job.getJobType().equals("Bribe")) {
				playerCityRelate.setLeverage(playerCityRelate.getLeverage()+(2*job.getReward()));
			} else {
				PlayerResource playerGold = player.getResource("Gold");
				playerGold.setAmount(playerGold.getAmount()+Math.round(job.getReward()+(.1*playerCityRelate.getFavor())));				
				playerCityRelate.setFavor(playerCityRelate.getFavor()+1);				
			}
			j.setStatus("Complete");
		} finally {
			pm.close();
		}
	}
	
	public UnitTypeDTO[] GetUnitTypes(String faction, boolean mercs) throws NotLoggedInException {
		checkLoggedIn();
		
		String searchFaction = faction;
		if (mercs) {
			if (faction.equals("Khador")) searchFaction = "Ord";
			if (faction.equals("Cygnar")) searchFaction = "Llael";
		}
		String filter = "faction == f";
		if (searchFaction.equals("Ord") || searchFaction.equals("Llael")) {
			filter += " || faction == 'Both'";
		}
				
		PersistenceManager pm = getPersistenceManager();
		List<UnitTypeDTO> uTypeDTOs = new ArrayList<UnitTypeDTO>();
		try {
			Query q = pm.newQuery(UnitType.class);			
			q.setFilter(filter);
			q.declareParameters("String f");
			q.setOrdering("modelType desc, name");
			List<UnitType> unitTypes = (List<UnitType>) q.execute(searchFaction);
			for (UnitType utype : unitTypes) {
				UnitTypeDTO utd = new UnitTypeDTO();
				copy(utype, utd);
				uTypeDTOs.add(utd);				
			}
		} finally {
			pm.close();
		}
		return (UnitTypeDTO[]) uTypeDTOs.toArray(new UnitTypeDTO[0]);
	}
	
	public void PrimeData() {
		PersistenceManager pm = getPersistenceManager();
		try {
			PrimeData.Prime(pm);
		} finally {
			pm.close();
		}
	}
	
	public UnitDTO BuyUnit(UnitTypeDTO unitType) throws NotLoggedInException {
		checkLoggedIn();
		
		PersistenceManager pm = getPersistenceManager();
		try {
			Player player = getPlayer(getUser().getEmail(),pm);
			PlayerDTO pDTO = new PlayerDTO();
			copy(player, pDTO);
			
			int unitCount = 0;
			for (Unit unit : player.getUnits()) {
				if (unit.getName().equals(unitType.getName()))
					unitCount++;
			}			
			if (unitCount >= unitType.getFieldAllowance()) {
				return null;
			}
			
			Long pointLimit = PlayerDTO.getPointLimit(player.getLevel());			
			if (pointLimit < (pDTO.getArmySize() + unitType.getMinPoints())) {
				return null;
			}
			
			player.setLastSpentDate(new Date());
			
			List<ResourceAmountDTO> cost = unitType.getPurchaseCost(player.getFaction());
			for (ResourceAmountDTO rac : cost) {
				PlayerResource pr = player.getResource(rac.getResource());
				pr.setAmount(pr.getAmount()-rac.getAmount());
			}		
						
			Unit u = new Unit();
			u.setOwnerEmail(getUser().getEmail());
			u.setName(unitType.getName());
			u.setPoints(unitType.getMinPoints());
			u.setLastPaid(new Date());
			u.setUnitType(GetUnitType(pm,unitType.getName()));
			pm.makePersistent(u);
			
			UnitDTO udto = new UnitDTO();
			copy(u,udto);
			return udto;
			
		} finally {
			pm.close();
		}
	}
	
	public String UpgradeUnit(UnitDTO unit) throws NotLoggedInException {
		checkLoggedIn();
		
		PersistenceManager pm = getPersistenceManager();
		try	{
			Player thisPlayer = getPlayer(getUser().getEmail(),pm);
			PlayerDTO pDTO = new PlayerDTO();
			copy(thisPlayer, pDTO);
			
			Long pointsAway = unit.getUpgradePointValue();
			if ((pDTO.getArmySize() + pointsAway) > PlayerDTO.getPointLimit(thisPlayer.getLevel())) {
				return "Cannot upgrade because you're at your max army size";
			}		
			List<ResourceAmountDTO> upgradeCost = unit.getUpgradeCost(thisPlayer.getFaction());
			if (!pDTO.canPlayerAffordThis(upgradeCost)) {
				return "Cannot upgrade because can't afford this";
			}
			
			thisPlayer.setLastSpentDate(new Date());
			
			for (ResourceAmountDTO rac : upgradeCost) {
				PlayerResource pr = thisPlayer.getResource(rac.getResource());
				pr.setAmount(pr.getAmount()-rac.getAmount());				
			}
			
			Query q = pm.newQuery(Unit.class);
			q.setFilter("id == i");
			q.declareParameters("Long i");
			List<Unit> results = (List<Unit>)q.execute(unit.getId());
			for (Unit u : results) {
				u.setPoints(u.getPoints() + pointsAway);
				return "Unit Upgraded";
			}			
		} finally {
			pm.close();
		}
		return "Unable to find unit to upgrade";
	}
	
	public void Forage() throws NotLoggedInException {
		checkLoggedIn();
			
		PersistenceManager pm = getPersistenceManager();
		try {			
			Player thisPlayer = getPlayer(getUser().getEmail(),pm);
			PlayerResource pr = thisPlayer.getResource("Food");
			pr.setAmount(pr.getAmount() + 10L);
			
			thisPlayer.setLastForageDate(new Date());
			
		} finally {
			pm.close();
		}
	}
	
	public void CancelEspionage() throws NotLoggedInException {
		checkLoggedIn();
		
		PersistenceManager pm = getPersistenceManager();
		try {
			Player player = getPlayer(getUser().getEmail(),pm);
			PlayerDTO pDTO = new PlayerDTO();
			copy(player, pDTO);
			
			for (Job job : player.getJobs()) {
				if ((job.getStatus().equals("Pending") || 
					 job.getStatus().equals("Incomplete")) &&
					(job.getJobType().equals("Warmonger") ||
					 job.getJobType().equals("Surveillance") ||
					 job.getJobType().equals("Bribe"))) {
					job.setStatus("Canceled");
				}
			}
		} finally {
			pm.close();
		}
	}
	
	public void Extort(String cityName) throws NotLoggedInException {
		checkLoggedIn();
		
		PersistenceManager pm = getPersistenceManager();
		try {
			Player player = getPlayer(getUser().getEmail(),pm);
			PlayerCity city = player.getCity(cityName);
			PlayerResource gold = player.getResource("Gold");
			gold.setAmount(gold.getAmount()+(city.getLeverage()*PlayerDTO.GOLD_PER_LEVERAGE));
			city.setFavor(-5-city.getLeverage());
			city.setLeverage(0L);			
		} finally {
			pm.close();
		}
	}
	
	public void UpdateBio(String bio) throws NotLoggedInException {
		checkLoggedIn();
		
		PersistenceManager pm = getPersistenceManager();
		try {
			Player player = getPlayer(getUser().getEmail(),pm);
			player.setCharacterDescription(bio);			
		} finally {
			pm.close();
		}
	}
	public void IncrementStat(String email, PlayerDTO.Stat s) throws NotLoggedInException {
		checkLoggedIn(); 
		
		PersistenceManager pm = getPersistenceManager();
		try {
			Player player = getPlayer(email,pm);
			switch (s){
			case Level: 
				player.setLevel(player.getLevel()+1);
				break;
			case EspionageLevel:
				player.setEspionageLevel(player.getEspionageLevel()+1);
				break;
			case NarrationPoints:
				player.setNarrationPoints(player.getNarrationPoints()+1);
				break;
			}			
		} finally {
			pm.close();
		}
	}
	
	//utility
	private void SetCurrentUserInfo(PlayerDTO info, String requestUri) throws NotLoggedInException {
		checkLoggedIn();
			    
	    User user = getUser();
	    UserService userService = UserServiceFactory.getUserService();
	    
	    info.setLogoutUrl(userService.createLogoutURL(requestUri));	    
    	info.setEmailAddress(user.getEmail());
    	info.setAdmin(userService.isUserAdmin());
    	info.setNickName(user.getNickname());
    	info.setCurrentPlayer(true);    	
	}
	
	private Player getPlayer(String email, PersistenceManager pm) throws NotLoggedInException {
		checkLoggedIn();
		
		Player thisPlayer = null;
		
		Query p = pm.newQuery(Player.class);
		p.setFilter("email == e");
		p.declareParameters("String e");
		List<Player> players = (List<Player>) p.execute(email);
		if (players.size() > 0) {
			thisPlayer = players.get(0);
			GetPlayerUnits(thisPlayer,pm);
		}
				
		return thisPlayer;		
	}
	private void GetPlayerUnits(Player thisPlayer, PersistenceManager pm) throws NotLoggedInException {
		Query q = pm.newQuery(Unit.class);
		q.setFilter("ownerEmail == e");
		q.declareParameters("String e");			
		List<Unit> units = (List<Unit>) q.execute(thisPlayer.getEmail());
		for (Unit unit : units) {
			unit.setUnitType(GetUnitType(pm, unit.getName()));
			thisPlayer.getUnits().add(unit);
		}
	}
	
	public void copy(Player p, PlayerDTO dto) {
		dto.setEmailAddress(p.getEmail());
		dto.setCharacterName(p.getCharacterName());
		dto.setCharacterDescription(p.getCharacterDescription());
		dto.setOriginLatitude(p.getOriginLatitude());
		dto.setOriginLongitude(p.getOriginLongitude());
		dto.setDestLatitude(p.getDestLatitude());
		dto.setDestLongitude(p.getDestLongitude());
		dto.setMoveStart(p.getMoveStart());
		dto.setDoneMapTutorial(p.isDoneMapTutorial());
		dto.setDoneJobTutorial(p.isDoneJobTutorial());
		dto.setDoneEspionageTutorial(p.isDoneEspionageTutorial());
		dto.setDoneHireTutorial(p.isDoneHireTutorial());
		dto.setEspionageLevel(p.getEspionageLevel());
		dto.setFaction(p.getFaction());
		dto.setLevel(p.getLevel());
		dto.setLastForageDate(p.getLastForageDate());
		dto.setNickName(p.getNickName());
		dto.setImageURL(p.getImageURL());
		dto.setNarrationPoints(p.getNarrationPoints());
		
		for (PlayerResource pr : p.getResources()) {
			ResourceAmountDTO prc = new ResourceAmountDTO();
			prc.setResource(pr.getResource());
			prc.setAmount(pr.getAmount());
			dto.getResources().add(prc);
		}				
		
		for (PlayerCity pc : p.getCities()) {
			PlayerCityDTO pcd = new PlayerCityDTO();
			pcd.setCity(pc.getCity());
			pcd.setFavor(pc.getFavor());
			pcd.setLeverage(pc.getLeverage());
			pcd.setEmail(pc.getEmail());
			dto.getCities().add(pcd);
		}
		
		for (Unit unit : p.getUnits()) {
			UnitDTO ud = new UnitDTO();
			copy(unit,ud);
			dto.getUnits().add(ud);
		}

		for (Job job : p.getJobs()) {
			JobDTO jd = new JobDTO();
			copy(job,jd);
			dto.getJobs().add(jd);
		}
	}
	public void copy(Job j, JobDTO dto) {
		dto.setId(j.safeKey());
		dto.setDestination(j.getDestination());
		dto.setEmail(j.getEmail());
		dto.setJobFor(j.getJobFor());
		dto.setStatus(j.getStatus());
		dto.setJobType(j.getJobType());
		dto.setReward(j.getReward());
		dto.setTaken(j.getTaken());
		dto.setStoryMessageID(j.getStoryMessageID());
		dto.setStorySubject(j.getStorySubject());
	}
	public void copy(UnitType u, UnitTypeDTO dto) {
		dto.setId(u.getId());
		dto.setName(u.getName());
		dto.setFieldAllowance(u.getFieldAllowance());
		dto.setMinPoints(u.getMinPoints());
		dto.setMaxPoints(u.getMaxPoints());
		dto.setHref(u.getHref());
		dto.setAttached(u.getAttached());
		dto.setFaction(u.getFaction());
		dto.setModelType(u.getModelType());
		
		for (UnitTypeResource pr : u.getResources()) {
			ResourceAmountDTO prc = new ResourceAmountDTO();
			prc.setResource(pr.getResource());
			prc.setAmount(pr.getAmount());
			dto.getResources().add(prc);
		}
	}
	public void copy(Unit u, UnitDTO dto) {
		dto.setId(u.getId());
		dto.setName(u.getName());
		dto.setOwnerEmail(u.getOwnerEmail());
		dto.setPoints(u.getPoints());
		dto.setLastPaid(u.getLastPaid());
		
		UnitTypeDTO utd = new UnitTypeDTO();
		copy(u.getUnitType(), utd);
		
		dto.setUnitType(utd);
	}
	
	private UnitType GetUnitType(PersistenceManager pm, String name) throws NotLoggedInException {
		Query q = pm.newQuery(UnitType.class);
		q.setFilter("name == n");
		q.declareParameters("String n");
		List<UnitType> unitTypes = (List<UnitType>) q.execute(name);
		for (UnitType utype : unitTypes) {
			return utype;
		}
		throw new NotLoggedInException("Unable to find Unit Type: "+name);		
	}
	
	//other stuff
	
/*	public PlayerClient[] getPlayers() throws NotLoggedInException {
		checkLoggedIn();
		PersistenceManager pm = getPersistenceManager();
		
		List<PlayerClient> playerClients = new ArrayList<PlayerClient>();		
		try {
			Query q = pm.newQuery(Player.class);
			q.setOrdering("email");
			List<Player> players = (List<Player>) q.execute();			
			for (Player player : players) {
				PlayerClient p = new PlayerClient();
				p.setEmailAddress(player.getEmail());
				p.setLevel(player.getLevel());
				p.setLatitude(player.getLatitude());
				p.setLongitude(player.getLongitude());
				playerClients.add(p);		
			}
		} finally {
			pm.close();
		}
		return (PlayerClient[]) playerClients.toArray(new PlayerClient[0]);
	}	
	
	//Unit Types
	public Long addUnitType(UnitTypeClient unitTypeClient) throws NotLoggedInException {
		UnitType u = new UnitType();
		checkLoggedIn();
		PersistenceManager pm = getPersistenceManager();
		try {			
			u.setName(unitTypeClient.getName());
			u.setFieldAllowance(unitTypeClient.getFieldAllowance());
			u.setMinPoints(unitTypeClient.getMinPoints());
			u.setMinMen(unitTypeClient.getMinMen());
			u.setMaxPoints(unitTypeClient.getMaxPoints());
			u.setMaxMen(unitTypeClient.getMaxMen());
			u.setHref(unitTypeClient.getHref());
			u.setMinLevel(unitTypeClient.getMinLevel());
			u.setAttached(unitTypeClient.getAttached());
			u.setWarning(unitTypeClient.getWarning());
			pm.makePersistent(u);
		} finally {
			pm.close();
		}
		return u.getId();
	}
	public void removeUnitType(Long id) throws NotLoggedInException {
		checkLoggedIn();
		PersistenceManager pm = getPersistenceManager();
		try {
		  long deleteCount = 0;
		  Query q = pm.newQuery(UnitType.class);		   
		  List<UnitType> unitTypes = (List<UnitType>) q.execute();
		  for (UnitType unitType : unitTypes) {
		    if (id.equals(unitType.getId())) {
		      deleteCount++;
		      pm.deletePersistent(unitType);
		    }
		  }
		  if (deleteCount != 1) {
		   LOG.log(Level.WARNING, "removeUnitType deleted "+deleteCount+" Message");
		  }
		} finally {
		  pm.close();
		}
	}
	public UnitTypeClient[] getUnitTypes() throws NotLoggedInException {
		checkLoggedIn();
		
		PersistenceManager pm = getPersistenceManager();
		List<UnitTypeClient> uTypeClients = new ArrayList<UnitTypeClient>();
		try {
			Query q = pm.newQuery(UnitType.class);
			q.setOrdering("minPoints, name");
			List<UnitType> unitTypes = (List<UnitType>) q.execute();
			for (UnitType utype : unitTypes) {
				uTypeClients.add(mapUnitType(utype));				
			}
		} finally {
			pm.close();
		}
		return (UnitTypeClient[]) uTypeClients.toArray(new UnitTypeClient[0]);
	}
	public void UpdateCost(Long id, String resource) throws NotLoggedInException {
		checkLoggedIn();
		
		PersistenceManager pm = getPersistenceManager();		
		try {
			Query p = pm.newQuery(UnitType.class);
			p.setFilter("id == i");
			p.declareParameters("Long i");
			List<UnitType> unitTypes = (List<UnitType>) p.execute(id);
			for (UnitType ut : unitTypes) {
				UnitTypeResource theResource = null;
				for (UnitTypeResource utr : ut.getResources()) {
					if (utr.getResource().equalsIgnoreCase(resource)) {
						theResource = utr;
					}					
				}
				if (theResource == null) {
					//didn't find it, create it
					theResource = new UnitTypeResource();
					theResource.setResource(resource);
					theResource.setAmount(0L);
					ut.getResources().add(theResource);
				}
				theResource.setAmount(theResource.getAmount()+1L);
			}
		} finally {
			pm.close();
		}
	}
	
	//Units
	public void removeUnit(Long id) throws NotLoggedInException {
	  checkLoggedIn();
	  PersistenceManager pm = getPersistenceManager();
	  try {
	    long deleteCount = 0;
	    Query q = pm.newQuery(Unit.class);	     
	    List<Unit> units = (List<Unit>) q.execute();
	    for (Unit unit : units) {
	      if (id.equals(unit.getId())) {
	        deleteCount++;
	        pm.deletePersistent(unit);
	      }
	    }
	    if (deleteCount != 1) {
	      LOG.log(Level.WARNING, "removeMessage deleted "+deleteCount+" Message");
	    }
	  } finally {
	    pm.close();
	  }
	}
	*/
	//resources
		
	//other
	private void checkLoggedIn() throws NotLoggedInException {
	  if (getUser() == null) {
	    throw new NotLoggedInException("Not logged in.");
	  }
	}
	
	private User getUser() {
	  UserService userService = UserServiceFactory.getUserService();
	  return userService.getCurrentUser();
	}

	private PersistenceManager getPersistenceManager() {
	  return PMF.getPersistenceManager();
	}
}
